﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json.Serialization;
using Devonline.Core;
using Newtonsoft.Json;

namespace Devonline.Http
{
    /// <summary>
    /// 查询选项
    /// </summary>
    public class QueryOptions
    {
        /// <summary>
        /// 当前表达式的类型主体
        /// </summary>
        private readonly Type _type;
        /// <summary>
        /// 当前类型的公开成员列表
        /// </summary>
        private readonly MemberInfo[] _memberInfos;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public QueryOptions()
        {
            _memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
        }
        /// <summary>
        /// 使用原始字符串表达式的构造函数
        /// </summary>
        /// <param name="queryOption"></param>
        public QueryOptions(Type type, QueryOptionRawValue queryOption)
        {
            _type = type;
            _memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance);

            Count = queryOption.Count;
            Top = queryOption.Top;
            Skip = queryOption.Skip;

            if (queryOption.Filter.IsNotNullOrWhiteSpace())
            {
                //TODO TBC
                Filter = new FilterOption(_type, queryOption.Filter);
            }

            if (queryOption.Orderby.IsNotNullOrWhiteSpace())
            {
                Orderby = new OrderbyOption(_type, queryOption.Orderby);
            }

            if (queryOption.Select.IsNotNullOrWhiteSpace())
            {
                Select = queryOption.Select.Split(AppSettings.CHAR_COMMA, StringSplitOptions.RemoveEmptyEntries);

                var fields = Select.Where(x => !_memberInfos.Any(a => x == a.Name)).ToList();
                if (fields.Any())
                {
                    throw new ArgumentException($"the properties or fields {fields.ToString<string>()} of type {_type.Name} not found!");
                }
            }

            if (queryOption.Expand.IsNotNullOrWhiteSpace())
            {
                //TODO expand 功能暂不实现
                Expand = new QueryOptions(_type, new QueryOptionRawValue(queryOption.Expand));
            }
        }

        /// <summary>
        /// 是否返回总数量
        /// </summary>
        [JsonProperty("$count")]
        [JsonPropertyName("$count")]
        public bool? Count { get; set; }
        /// <summary>
        /// 当前页码
        /// </summary>
        [JsonProperty("$top")]
        [JsonPropertyName("$top")]
        public int? Top { get; set; }
        /// <summary>
        /// 页大小
        /// </summary>
        [JsonProperty("$skip")]
        [JsonPropertyName("$skip")]
        public int? Skip { get; set; }
        /// <summary>
        /// 查询/过滤选项
        /// </summary>
        [JsonProperty("$filter")]
        [JsonPropertyName("$filter")]
        public FilterOption Filter { get; set; }
        /// <summary>
        /// 排序选项
        /// </summary>
        [JsonProperty("$orderby")]
        [JsonPropertyName("$orderby")]
        public OrderbyOption Orderby { get; set; }
        /// <summary>
        /// 列选项
        /// </summary>
        [JsonProperty("$select")]
        [JsonPropertyName("$select")]
        public IEnumerable<string> Select { get; set; }
        /// <summary>
        /// 扩展选项
        /// </summary>
        [JsonProperty("$expand")]
        [JsonPropertyName("$expand")]
        public QueryOptions Expand { get; set; }

        /// <summary>
        /// 重载的 ToString 方法返回 QueryOptions 的字符串表达式
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            var result = new List<string>();

            if (Count.HasValue && Count.Value)
            {
                result.Add("$count=true");
            }

            if (Top.HasValue && Top.Value > 0)
            {
                result.Add($"$top={Top.Value}");
            }

            if (Skip.HasValue && Skip.Value > 0)
            {
                result.Add($"$skip={Skip.Value}");
            }

            if (Filter != null)
            {
                result.Add($"$filter={Filter}");
            }

            if (Orderby != null)
            {
                result.Add($"$orderby={Orderby}");
            }

            if (Select != null)
            {
                result.Add($"Select={string.Join(AppSettings.CHAR_COMMA, Select)}");
            }

            if (Expand != null)
            {
                result.Add($"$expand={Expand}");
            }

            return string.Join(AppSettings.CHAR_ADD, result);
        }
    }

    /// <summary>
    /// 查询选项
    /// </summary>
    public class QueryOptions<T>
    {
        /// <summary>
        /// 当前表达式的类型主体
        /// </summary>
        private readonly Type _type = typeof(T);
        /// <summary>
        /// 当前类型的公开成员列表
        /// </summary>
        private readonly MemberInfo[] _memberInfos;

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public QueryOptions()
        {
            _memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
        }
        /// <summary>
        /// 使用原始字符串表达式的构造函数
        /// </summary>
        /// <param name="queryOption"></param>
        public QueryOptions(QueryOptionRawValue queryOption)
        {
            _memberInfos = _type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

            Count = queryOption.Count;
            Top = queryOption.Top;
            Skip = queryOption.Skip;

            if (queryOption.Filter.IsNotNullOrWhiteSpace())
            {
                if (NestedFilterOption<T>.LogicExpression.Any(x => queryOption.Filter.Contains(x)))
                {
                    Filter = new NestedFilterOption<T>(queryOption.Filter);
                }
                else
                {
                    Filter = new FilterOption<T>(queryOption.Filter);
                }
            }

            if (queryOption.Orderby.IsNotNullOrWhiteSpace())
            {
                Orderby = new OrderbyOption<T>(queryOption.Orderby);
            }

            if (queryOption.Select.IsNotNullOrWhiteSpace())
            {
                Select = queryOption.Select.Split(AppSettings.CHAR_COMMA, StringSplitOptions.RemoveEmptyEntries);

                var fields = Select.Where(x => !_memberInfos.Any(a => x == a.Name)).ToList();
                if (fields.Any())
                {
                    throw new ArgumentException($"the properties or fields {fields.ToString<string>()} of type {_type.Name} not found!");
                }
            }

            if (queryOption.Expand.IsNotNullOrWhiteSpace())
            {
                //TODO expand 功能暂不实现
                Expand = new QueryOptions<T>(new QueryOptionRawValue(queryOption.Expand));
            }
        }

        /// <summary>
        /// 是否返回总数量
        /// </summary>
        [JsonProperty("$count")]
        [JsonPropertyName("$count")]
        public bool? Count { get; set; }
        /// <summary>
        /// 当前页码
        /// </summary>
        [JsonProperty("$top")]
        [JsonPropertyName("$top")]
        public int? Top { get; set; }
        /// <summary>
        /// 页大小
        /// </summary>
        [JsonProperty("$skip")]
        [JsonPropertyName("$skip")]
        public int? Skip { get; set; }
        /// <summary>
        /// 查询/过滤选项
        /// </summary>
        [JsonProperty("$filter")]
        [JsonPropertyName("$filter")]
        public FilterOption<T> Filter { get; set; }
        /// <summary>
        /// 排序选项
        /// </summary>
        [JsonProperty("$orderby")]
        [JsonPropertyName("$orderby")]
        public OrderbyOption<T> Orderby { get; set; }
        /// <summary>
        /// 列选项
        /// </summary>
        [JsonProperty("$select")]
        [JsonPropertyName("$select")]
        public IEnumerable<string> Select { get; set; }
        /// <summary>
        /// 扩展选项
        /// </summary>
        [JsonProperty("$expand")]
        [JsonPropertyName("$expand")]
        public QueryOptions<T> Expand { get; set; }

        /// <summary>
        /// 重载的 ToString 方法返回 QueryOptions 的字符串表达式
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            var result = new List<string>();

            if (Count.HasValue && Count.Value)
            {
                result.Add("$count=true");
            }

            if (Top.HasValue && Top.Value > 0)
            {
                result.Add($"$top={Top.Value}");
            }

            if (Skip.HasValue && Skip.Value > 0)
            {
                result.Add($"$skip={Skip.Value}");
            }

            if (Filter != null)
            {
                result.Add($"$filter={Filter}");
            }

            if (Orderby != null)
            {
                result.Add($"$orderby={Orderby}");
            }

            if (Select != null)
            {
                result.Add($"Select={string.Join(AppSettings.CHAR_COMMA, Select)}");
            }

            if (Expand != null)
            {
                result.Add($"$expand={Expand}");
            }

            return string.Join(AppSettings.CHAR_ADD, result);
        }
    }
}
